﻿using System.Collections.Generic;
using System.Linq;
using LFloatMath.Math;

namespace IQIGame.Onigao.GamePlay
{
    public class BuffViewComponent : TComponent
    {
        public List<BuffView> buffs = new List<BuffView>();
        public UnitView unit;

        public int shield;

        protected override void OnDispose()
        {
        }

        public override void OnCreate(TEntity entity)
        {
            this.unit = entity as UnitView;
        }

        public void OnBuffAdd(BuffData rData)
        {
            var nBuffID = rData.buffID;
            var nStack = rData.stack;
            var nDuration = rData.timeDuration;
            BuffView rView = this.Get(nBuffID, out var bIsNew);
            rView.stack = nStack;
            rView.duration = nDuration;
            rView.startTime = rData.timeStart;

            this.ChangeEffectOnStackChanged(rView);
        }

        public void OnBuffRemove(BuffData rData)
        {
            var nBuffID = rData.buffID;
            var nStack = rData.stack;
            var nDuration = rData.timeDuration;
            BuffView rView = this.Get(nBuffID, out _);
            rView.stack = nStack;
            rView.duration = nDuration;
            rView.startTime = rData.timeStart;
            this.ChangeEffectOnStackChanged(rView);
        }

        public void OnDestroy(BuffData rBuff)
        {
            BuffView rView = this.Get(rBuff.buffID, out _);
            var rEffectComp = this.unit.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
            rEffectComp?.RemoveEffect(rView.effectGuid);
            this.buffs.Remove(rView);
        }

        private BuffView Get(int nBuffID, out bool isNew)
        {
            BuffView rView = null;
            isNew = false;
            for (int i = 0; i < this.buffs.Count; i++)
            {
                var rBuff = this.buffs[i];
                if (rBuff.buffID == nBuffID)
                {
                    rView = rBuff;
                    break;
                }
            }
            if (rView == null)
            {
                rView = new BuffView()
                {
                    buffID = nBuffID,
                };
                this.buffs.Add(rView);
                isNew = true;
            }

            return rView;
        }

        private void ChangeEffectOnStackChanged(BuffView buff)
        {
            var nNewIndex = buff.stack - 1;
            var rBuffConfig = TableCenter.buff.Get(buff.buffID);
            var rNewName = string.Empty;
            if (rBuffConfig.EffectView.Count > nNewIndex && nNewIndex >= 0)
            {
                rNewName = rBuffConfig.EffectView[nNewIndex];
            }
            if (string.IsNullOrEmpty(rNewName))
            {
                for (int i = 0; i < rBuffConfig.EffectView.Count; i++)
                {
                    var nIndex = rBuffConfig.EffectView.Count - 1 - i;
                    if (nIndex <= nNewIndex && string.IsNullOrEmpty(rBuffConfig.EffectView[nIndex]))
                    {
                        rNewName = rBuffConfig.EffectView[nIndex];
                        break;
                    }
                }
            }
            if (rNewName != buff.effectName && !string.IsNullOrEmpty(rNewName))
            {
                var rEffectComp = this.unit.GetComponent<EffectComponent>(ETComponentType.EffectComponent);
                if (buff.effectGuid != 0)
                {
                    rEffectComp.RemoveEffect(buff.effectGuid);
                    buff.effectGuid = 0;
                    buff.effectName = string.Empty;
                }

                var rSpace = rBuffConfig.EffectType switch
                {
                    1 => EVFXSpace.Local,
                    2 => EVFXSpace.LocalPosition,
                    3 => EVFXSpace.World,
                    _ => EVFXSpace.Auto
                };
                var nGuid = rEffectComp.AddBuffEffect(rNewName, rBuffConfig.EffectDummy, rSpace, rBuffConfig.EffectLoop);
                if (rBuffConfig.EffectLoop)
                {
                    buff.effectGuid = nGuid;
                    buff.effectName = rNewName;
                }
            }
        }
    }

    public class BuffView
    {
        public int buffID;
        public int stack;
        public int duration;
        public int startTime;

        public string effectName;
        public uint effectGuid;
    }
}